export const useTagsViewStore = defineStore(
  "tagsView",
  () => {
    const visitedViews = ref<TagView[]>([]);
    const cachedViews = ref<string[]>([]);
    const router = useRouter();
    const route = useRoute();

    /**
     * 添加已访问视图到已访问视图列表中
     */
    function addVisitedView(view: TagView) {
      // 如果已经存在于已访问的视图列表中，则不再添加
      if (visitedViews.value.some((v) => v.path === view.path)) {
        return;
      }
      // 如果视图是固定的（affix），则在已访问的视图列表的开头添加
      if (view.affix) {
        visitedViews.value.unshift(view);
      } else {
        // 如果视图不是固定的，则在已访问的视图列表的末尾添加
        visitedViews.value.push(view);
      }
    }

    /**
     * 添加缓存视图到缓存视图列表中
     */
    function addCachedView(view: TagView) {
      const viewName = view.name;
      // 如果缓存视图名称已经存在于缓存视图列表中，则不再添加
      if (cachedViews.value.includes(viewName)) {
        return;
      }

      // 如果视图需要缓存（keepAlive），则将其路由名称添加到缓存视图列表中
      if (view.keepAlive) {
        cachedViews.value.push(viewName);
      }
    }

    /**
     * 从已访问视图列表中删除指定的视图
     */
    function delVisitedView(view: TagView) {
      return new Promise((resolve) => {
        for (const [i, v] of visitedViews.value.entries()) {
          // 找到与指定视图路径匹配的视图，在已访问视图列表中删除该视图
          if (v.path === view.path) {
            visitedViews.value.splice(i, 1);
            break;
          }
        }
        resolve([...visitedViews.value]);
      });
    }

    function delCachedView(view: TagView) {
      const viewName = view.name;
      return new Promise((resolve) => {
        const index = cachedViews.value.indexOf(viewName);
        index > -1 && cachedViews.value.splice(index, 1);
        resolve([...cachedViews.value]);
      });
    }

    function delOtherVisitedViews(view: TagView) {
      return new Promise((resolve) => {
        visitedViews.value = visitedViews.value.filter((v) => {
          return v?.affix || v.path === view.path;
        });
        resolve([...visitedViews.value]);
      });
    }

    function delOtherCachedViews(view: TagView) {
      const viewName = view.name as string;
      return new Promise((resolve) => {
        const index = cachedViews.value.indexOf(viewName);
        if (index > -1) {
          cachedViews.value = cachedViews.value.slice(index, index + 1);
        } else {
          // if index = -1, there is no cached tags
          cachedViews.value = [];
        }
        resolve([...cachedViews.value]);
      });
    }

    function updateVisitedView(view: TagView) {
      for (let v of visitedViews.value) {
        if (v.path === view.path) {
          v = Object.assign(v, view);
          break;
        }
      }
    }

    function addView(view: TagView) {
      addVisitedView(view);
      addCachedView(view);
    }

    function delView(view: TagView) {
      return new Promise((resolve) => {
        delVisitedView(view);
        delCachedView(view);
        resolve({
          visitedViews: [...visitedViews.value],
          cachedViews: [...cachedViews.value],
        });
      });
    }

    function delOtherViews(view: TagView) {
      return new Promise((resolve) => {
        delOtherVisitedViews(view);
        delOtherCachedViews(view);
        resolve({
          visitedViews: [...visitedViews.value],
          cachedViews: [...cachedViews.value],
        });
      });
    }

    function delLeftViews(view: TagView) {
      return new Promise((resolve) => {
        const currIndex = visitedViews.value.findIndex(
          (v) => v.path === view.path
        );
        if (currIndex === -1) {
          return;
        }
        visitedViews.value = visitedViews.value.filter((item, index) => {
          if (index >= currIndex || item?.affix) {
            return true;
          }

          const cacheIndex = cachedViews.value.indexOf(item.name);
          if (cacheIndex > -1) {
            cachedViews.value.splice(cacheIndex, 1);
          }
          return false;
        });
        resolve({
          visitedViews: [...visitedViews.value],
        });
      });
    }

    function delRightViews(view: TagView) {
      return new Promise((resolve) => {
        const currIndex = visitedViews.value.findIndex(
          (v) => v.path === view.path
        );
        if (currIndex === -1) {
          return;
        }
        visitedViews.value = visitedViews.value.filter((item, index) => {
          if (index <= currIndex || item?.affix) {
            return true;
          }
        });
        resolve({
          visitedViews: [...visitedViews.value],
        });
      });
    }

    function delAllViews() {
      return new Promise((resolve) => {
        const affixTags = visitedViews.value.filter((tag) => tag?.affix);
        visitedViews.value = affixTags;
        cachedViews.value = [];
        resolve({
          visitedViews: [...visitedViews.value],
          cachedViews: [...cachedViews.value],
        });
      });
    }

    function delAllVisitedViews() {
      return new Promise((resolve) => {
        const affixTags = visitedViews.value.filter((tag) => tag?.affix);
        visitedViews.value = affixTags;
        resolve([...visitedViews.value]);
      });
    }

    function delAllCachedViews() {
      return new Promise((resolve) => {
        cachedViews.value = [];
        resolve([...cachedViews.value]);
      });
    }

    /**
     * 关闭当前tagView
     */
    function closeCurrentView() {
      const tags: TagView = {
        name: route.name as string,
        title: route.meta.title as string,
        path: route.path,
        fullPath: route.fullPath,
        affix: route.meta?.affix,
        keepAlive: route.meta?.keepAlive,
        query: route.query,
      };
      delView(tags).then((res: any) => {
        if (isActive(tags)) {
          toLastView(res.visitedViews, tags);
        }
      });
    }

    function isActive(tag: TagView) {
      return tag.path === route.path;
    }

    function toLastView(visitedViews: TagView[], view?: TagView) {
      const latestView = visitedViews.slice(-1)[0];
      if (latestView && latestView.fullPath) {
        router.push(latestView.fullPath);
      } else {
        // now the default is to redirect to the home page if there is no tags-view,
        // you can adjust it according to your needs.
        if (view?.name === "Dashboard") {
          // to reload home page
          router.replace("/redirect" + view.fullPath);
        } else {
          router.push("/");
        }
      }
    }

    return {
      visitedViews,
      cachedViews,
      addVisitedView,
      addCachedView,
      delVisitedView,
      delCachedView,
      delOtherVisitedViews,
      delOtherCachedViews,
      updateVisitedView,
      addView,
      delView,
      delOtherViews,
      delLeftViews,
      delRightViews,
      delAllViews,
      delAllVisitedViews,
      delAllCachedViews,
      closeCurrentView,
      isActive,
      toLastView,
    };
  },
  {
    persist: true,
  }
);
